import {
  WebSocketGateway,
  SubscribeMessage,
  MessageBody,
  ConnectedSocket,
  OnGatewayConnection,
  OnGatewayDisconnect,
  WebSocketServer,
} from '@nestjs/websockets';
import { Socket, Server } from 'socket.io';

import { AuthService } from '../auth/auth.service';
import { SocketResponseHelper } from './socket-response.helper';
import {
  SocketEvent,
  SocketEventPayloads,
} from './interfaces/events.interface';
import { PrismaService } from '../../prisma/prisma.service';
import { message_message_type as MessageType } from '@prisma/client';

@WebSocketGateway({ cors: true })
export class SocketGateway implements OnGatewayConnection, OnGatewayDisconnect {
  @WebSocketServer()
  server: Server;

  // 用户 im_id -> 该用户所有 socket 连接集合（支持多设备）
  private onlineUsers = new Map<string, Set<Socket>>();

  // socket.id -> 最近心跳时间戳
  private socketHeartbeats = new Map<string, number>();

  private readonly HEARTBEAT_TIMEOUT = 30000; // 30秒超时断开

  constructor(
    private readonly authService: AuthService,
    private readonly prisma: PrismaService,
  ) {
    // 启动时定时检测心跳超时
    setInterval(() => this.checkHeartbeatTimeouts(), 10000);
  }

  async handleConnection(client: Socket) {
    try {
      const token = client.handshake.auth.token;
      if (!token) {
        SocketResponseHelper.sendError(client, {
          content: '请先登录',
          messageType: MessageType.error,
        });
        client.disconnect(true);
        return;
      }
      const { im_id } = await this.authService.validateToken(token);

      let userSockets = this.onlineUsers.get(im_id);
      if (!userSockets) {
        userSockets = new Set<Socket>();
        this.onlineUsers.set(im_id, userSockets);
      }
      userSockets.add(client);

      this.socketHeartbeats.set(client.id, Date.now());

      console.log(`用户 ${im_id} 连接，当前设备数：${userSockets.size}`);
    } catch (err) {
      console.error('连接鉴权失败:', err.message);
      SocketResponseHelper.sendError(client, {
        content: '登录过期',
        messageType: MessageType.error,
      });
      client.disconnect(true);
    }
  }

  handleDisconnect(client: Socket) {
    this.socketHeartbeats.delete(client.id);
    for (const [im_id, sockets] of this.onlineUsers.entries()) {
      if (sockets.has(client)) {
        sockets.delete(client);
        if (sockets.size === 0) {
          this.onlineUsers.delete(im_id);
          console.log(`用户 ${im_id} 所有设备断开`);
        } else {
          console.log(`用户 ${im_id} 剩余设备数：${sockets.size}`);
        }
        break;
      }
    }
  }

  @SubscribeMessage(SocketEvent.SendMessage)
  async onSendMessage(
    @MessageBody() data: SocketEventPayloads[SocketEvent.SendMessage],
    @ConnectedSocket() client: Socket,
  ) {
    try {
      const token = client.handshake.auth.token;
      const { im_id } = await this.authService.validateToken(token);
      console.log(im_id);

      // 存储消息
      const msg = await this.prisma.message.create({
        data: {
          sender_im_id: im_id,
          content: data.content,
          receiver_im_id: data.toIm_Id || null,
          group_id: data.roomId ? Number(data.roomId) : null,
          message_type: data.messageType,
        },
      });

      // 单聊推送
      if (data.toIm_Id) {
        const receiverSockets = this.onlineUsers.get(data.toIm_Id);
        if (receiverSockets) {
          for (const socket of receiverSockets) {
            socket.emit(SocketEvent.SendMessage, {
              from: im_id,
              content: data.content,
              messageType: data.messageType,
              send_time: msg.send_time,
              roomId: data.roomId || null,
            });
          }
        }
      }

      // 群聊推送（roomId 存在且没有单聊接收者时）
      else if (data.roomId) {
        // 查出群成员 im_id 列表（不包含自己）
        const members = await this.prisma.group_member.findMany({
          where: { group_id: Number(data.roomId), NOT: { user_info: { im_id } } },
          include: { user_info: true },
        });

        for (const member of members) {
          const memberImId = member.user_info.im_id;
          const memberSockets = this.onlineUsers.get(memberImId);
          if (memberSockets) {
            for (const socket of memberSockets) {
              socket.emit('receiveMessage', {
                id: msg.id,
                from: im_id,
                content: data.content,
                messageType: data.messageType,
                send_time: msg.send_time,
                roomId: data.roomId,
              });
            }
          }
        }
      }

    } catch (err) {
      console.error('消息处理失败:', err);
      SocketResponseHelper.sendError(client, {
        content: '消息发送失败',
        messageType: MessageType.error,
      });
    }
  }

  @SubscribeMessage(SocketEvent.HeartBeat)
  async heartBeat(
    @MessageBody() data: SocketEventPayloads[SocketEvent.HeartBeat],
    @ConnectedSocket() client: Socket,
  ) {
    try {
      this.socketHeartbeats.set(client.id, Date.now());
      await this.authService.validateToken(data.content);
      console.log(`💓 心跳来自 ${client.id}`);
    } catch {
      SocketResponseHelper.sendError(client, {
        content: '登录过期',
        messageType: MessageType.error,
      });
      client.disconnect(true);
    }
  }

  private checkHeartbeatTimeouts() {
    const now = Date.now();
    for (const [socketId, lastTime] of this.socketHeartbeats.entries()) {
      if (now - lastTime > this.HEARTBEAT_TIMEOUT) {
        const socket = this.server.sockets.sockets.get(socketId);
        if (socket) {
          console.warn(`⚠️ 心跳超时，断开连接: ${socketId}`);
          socket.disconnect(true);
        }
        this.socketHeartbeats.delete(socketId);
      }
    }
  }
}
